﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
using TrenchcoatRobots.Datatypes;
using System.Diagnostics;
using System;

namespace TrenchcoatRobots.Classes.ComponentClasses {
	class AnimatedTextureRenderer : Component {
		public Dictionary<string, Animation> RendererAnimations { get; set; }
		public Texture2D Texture { get; set; }
		public int CurrentFrame { get; private set; }
		public bool Playing { get; set; }
		public bool FlipHorizontal { get; set; }
		public bool FlipVertical { get; set; }
		public string CurrentAnimationName {
			get { return m_currentAnimName; }
			set {
				Debug.Assert( RendererAnimations.ContainsKey( value ), "Animation name does not exist!" );
				m_currentAnimName = value;
				m_currentAnimData = RendererAnimations[CurrentAnimationName];
			}
		}


		private double m_currentTime;
		private string m_currentAnimName;
		private bool m_reversing;
		private Animation m_currentAnimData;

		/// <summary>
		/// Stops the animation and resets it to 0
		/// </summary>
		public void Stop() {
			Playing = false;
			CurrentFrame = 0;
			m_currentTime = 0;
		}

		#region Constructors
		protected void InitRenderer() {
			CurrentFrame = 0;
			Playing = false;
			RendererAnimations = new Dictionary<string, Animation>();
			FlipHorizontal = false;
			FlipVertical = false;
		}

		/// <summary>
		/// Create a new AnimatedTextureRenderer
		/// </summary>
		/// <param name="gameObjectMethod">Delegate method to parent object</param>
		/// <param name="texture">Texture sheet for the animation</param>
		/// <param name="animation">Animation data</param>
		public AnimatedTextureRenderer( ParentMethod gameObjectMethod, Texture2D texture, string animName, Animation animation )
			: base( gameObjectMethod, "TextureRenderer", false ) {
			InitRenderer();
			this.Texture = texture;
			RendererAnimations.Add( animName, animation );
			m_currentAnimName = animName;
			m_currentAnimData = animation;
		}
		#endregion

		public override void Update( ref GameTime gameTime ) {
			if ( Playing ) {
				if ( m_currentAnimData.CurrentAnimPlayback == AnimationPlayback.Loop ) {
					m_currentTime += gameTime.ElapsedGameTime.TotalSeconds;
					if ( m_currentTime > m_currentAnimData.AnimationLength ) {
						m_currentTime -= m_currentAnimData.AnimationLength;
					}
				}
				if ( m_currentAnimData.CurrentAnimPlayback == AnimationPlayback.BackAndForth ) {
					if ( m_reversing ) {
						m_currentTime -= gameTime.ElapsedGameTime.TotalSeconds;
					}
					else {
						m_currentTime += gameTime.ElapsedGameTime.TotalSeconds;
					}
					if ( m_currentTime > m_currentAnimData.AnimationLength && !m_reversing ) {
						m_reversing = true;
					}
					else if ( m_currentTime < 0 ) {
						m_reversing = false;
					}
				}
				if ( m_currentAnimData.CurrentAnimPlayback == AnimationPlayback.Single ) {
					m_currentTime += gameTime.ElapsedGameTime.TotalSeconds;
					if ( m_currentTime > m_currentAnimData.AnimationLength ) {
						Stop();
					}
				}
				float progress = (float)( m_currentTime / m_currentAnimData.AnimationLength );
				CurrentFrame = (int)MathHelper.Clamp( (int)Math.Floor( m_currentAnimData.Frames.Count * progress ), 0, m_currentAnimData.Frames.Count - 1 );
			}
		}

		public override void Draw( ref SpriteBatch spriteBatch, ref TrenchcoatRobots.Datatypes.DrawInfo drawinfo ) {
			if (FlipHorizontal && FlipVertical) {
				spriteBatch.Draw(
					Texture,
					(Parent().Position + drawinfo.Camera.Position) * drawinfo.Camera.Zoom,
					m_currentAnimData.Frames[CurrentFrame],
					Color.White,
					MathHelper.ToRadians(Parent().Angle + 180),
					new Vector2(),
					1.0f * drawinfo.Camera.Zoom,
					SpriteEffects.None,
					0f
					);
			}
			else if (FlipHorizontal) {
				spriteBatch.Draw(
					Texture,
					(Parent().Position + drawinfo.Camera.Position) * drawinfo.Camera.Zoom,
					m_currentAnimData.Frames[CurrentFrame],
					Color.White,
					MathHelper.ToRadians(Parent().Angle),
					new Vector2(),
					1.0f * drawinfo.Camera.Zoom,
					SpriteEffects.FlipHorizontally,
					0f
					);
			}
			else if (FlipVertical) {
				spriteBatch.Draw(
					Texture,
					(Parent().Position + drawinfo.Camera.Position) * drawinfo.Camera.Zoom,
					m_currentAnimData.Frames[CurrentFrame],
					Color.White,
					MathHelper.ToRadians(Parent().Angle),
					new Vector2(),
					1.0f * drawinfo.Camera.Zoom,
					SpriteEffects.FlipVertically,
					0f
					);
			}
			else {
				spriteBatch.Draw(
					Texture,
					(Parent().Position + drawinfo.Camera.Position) * drawinfo.Camera.Zoom,
					m_currentAnimData.Frames[CurrentFrame],
					Color.White,
					MathHelper.ToRadians(Parent().Angle),
					new Vector2(),
					1.0f * drawinfo.Camera.Zoom,
					SpriteEffects.None,
					0f
					);
			}
		}
	}
}
